import Cesium, { Cartesian3 } from '../../../Ces/Cesium';
import NavigationControl from './NavigationControl.js';
import Utils from '../Core/Utils.js';

// 假设 Terria 类型，如果实际有定义请替换为准确类型
type Terria = any;

/**
 * The model for a zoom in control in the navigation control tool bar
 *
 * @alias ZoomOutNavigationControl
 * @constructor
 * @abstract
 *
 * @param {Terria} terria The Terria instance.
 * @param {boolean} zoomIn is used for zooming in (true) or out (false)
 */
class ZoomNavigationControl extends NavigationControl {
    // 控制名称，设置为控件的标题
    name: string = '';
    // 要在导航控件中显示的文本
    declare text: string;
    // 控件的 CSS 类名
    declare cssClass: string;
    // 缩放的相对量
    relativeAmount: number;

    constructor(terria: Terria, zoomIn: boolean) {
        super(terria);
        // 初始化控制名称
        // this.name = 'Zoom'+ (zoomIn? 'In' : 'Out');
        // 初始化显示文本
        this.text = zoomIn? '+' : '-';
        // 初始化 CSS 类名
        this.cssClass = 'navigation-control-icon-zoom-' + (zoomIn? 'in' : 'out');
        // 初始化缩放相对量
        this.relativeAmount = 1.5;
        if (zoomIn) {
            // 确保放大是缩小的逆操作，反之亦然
            this.relativeAmount = 1 / this.relativeAmount;
        }
    }

    // 当用户点击此控件时执行的操作
    activate(): void {
        this.zoom(this.relativeAmount);
    }

    // 执行缩放操作
    zoom(relativeAmount: number): void {
        // this.terria.analytics.logEvent('navigation', 'click', 'zoomIn');
        (this as any).isActive = true;

        if (Cesium.defined(this.terria)) {
            const scene = this.terria.scene;
            const sscc = scene.screenSpaceCameraController;
            // 如果缩放功能禁用则不执行
            if (!sscc.enableInputs ||!sscc.enableZoom) {
                return;
            }
            // TODO
            // if(scene.mode == Cesium.SceneMode.COLUMBUS_VIEW &&!sscc.enableTranslate) {
            //     return;
            // }

            const camera = scene.camera;
            let orientation: { [key: string]: number } | undefined;

            switch (scene.mode) {
                case Cesium.SceneMode.MORPHING:
                    break;
                case Cesium.SceneMode.SCENE2D:
                    camera.zoomIn(camera.positionCartographic.height * (1 - this.relativeAmount));
                    break;
                default:
                    let focus: Cartesian3 | undefined;
                    if (Cesium.defined(this.terria.trackedEntity)) {
                        focus = new Cesium.Cartesian3();
                    } else {
                        focus = Utils.getCameraFocus(this.terria, false);
                    }

                    if (!Cesium.defined(focus)) {
                        // 相机方向未指向地球，使用椭球地平线点作为焦点
                        const ray = new Cesium.Ray(camera.worldToCameraCoordinatesPoint(scene.globe.ellipsoid.cartographicToCartesian(camera.positionCartographic)), camera.directionWC);
                        focus = Cesium.IntersectionTests.grazingAltitudeLocation(ray, scene.globe.ellipsoid);

                        orientation = {
                            heading: camera.heading,
                            pitch: camera.pitch,
                            roll: camera.roll
                        };
                    } else {
                        orientation = {
                            direction: camera.direction,
                            up: camera.up
                        };
                    }

                    if (!Cesium.defined(focus)) {
                        return;
                    }
                    const cartesian3Scratch = new Cesium.Cartesian3();
                    const direction = Cesium.Cartesian3.subtract(camera.position, focus, cartesian3Scratch);
                    const movementVector = Cesium.Cartesian3.multiplyByScalar(direction, relativeAmount, direction);
                    const endPosition = Cesium.Cartesian3.add(focus, movementVector, focus);

                    if (Cesium.defined(this.terria.trackedEntity) || scene.mode === Cesium.SceneMode.COLUMBUS_VIEW) {
                        // 有时 flyTo 不起作用（跳到错误位置），所以直接设置位置而不进行动画
                        // 跟踪实体时不使用 flyTo，因为动画期间实体位置可能会改变
                        camera.position = endPosition;
                    } else {
                        camera.flyTo({
                            destination: endPosition,
                            orientation: orientation as { [key: string]: number },
                            duration: 0.5,
                            convert: false
                        });
                    }
            }
        }

        // this.terria.notifyRepaintRequired();
        (this as any).isActive = false;
    }
}

export default ZoomNavigationControl;
